#include "wx_pch.h"
#include "crypt.h"

Crypt::Crypt()
{
    k[0] = K0;
    k[1] = K1;
    k[2] = K2;
    k[3] = K3;
}

void Crypt::tean(long *v, long N)
{
    long y=v[0],  z=v[1];
    long limit,sum=0;
    if (N>0)
    {  /*  ENCRYPT  */
        limit=DELTA*N;
        while (sum!=limit)
        {
            y+=((z<<4)^(z>>5))  +  (z^sum)  +  k[sum&3];
            sum+=DELTA;
            z+=((y<<4)^(y>>5))  +  (y^sum)  +  k[(sum>>11)&3];
        }
    }
    else
    {  /*  DECRYPT  */
        sum=DELTA*(-N);
        while (sum)
        {
            z-=((y<<4)^(y>>5))  +  (y^sum)  +  k[(sum>>11)&3];
            sum-=DELTA;
            y-=((z<<4)^(z>>5))  +  (z^sum)  +  k[sum&3];
        }
    }
    v[0]=y;
    v[1]=z;
}

void Crypt::cl_enc_block(long  *v)
{
    tean(v,ROUNDS);
}

void Crypt::cl_dec_block(long  *v)
{
    tean(v,-ROUNDS);
}
wxString Crypt::enc(wxString s)
{
    size_t len_o = s.Length();
    size_t len_n = (len_o + (4 - len_o % 4)) / 2;

    long *tmp = new long[len_n];
    memset(tmp, 0, len_n*4);

    memcpy(tmp, s.c_str(), len_o*2);

    for(size_t i=0; i<len_n; i+=2)
    {
        cl_enc_block(tmp + i);
    }

    wxString r = _T("");
    for(size_t i=0; i<len_n; i++)
    {
        r = wxString::Format(_T("%s%08x"), r.c_str(), *(tmp+i));
    }

    delete[] tmp;
    return r;
}

wxString Crypt::dec(wxString s)
{
    if(s.Length() % 8) return _T("");
    size_t len_o = s.Length()/8;
    long *tmp = new long[len_o];
    for(size_t i=0; i<len_o; i++)
    {
        s.Mid(i*8, 8).ToULong((unsigned long*)(tmp+i), 16);
    }
    for(size_t i=0; i<len_o; i+=2)
    {
        cl_dec_block(tmp + i);
    }

    wchar_t *ret = new wchar_t[len_o*2];
    memcpy(ret, tmp, len_o*4);
    wxString r(ret);
    delete[] tmp;
    delete[] ret;
    return r;
}
